006.ReAct 与 Plan-and-Execute 设计模式
为什么需要 Agent 设计模式?
传统AI应用的局限性:
在 Agent 模式出现前,AI 应用大多是"单次问答"模式:
- 用户输入 → AI 一次性回答 → 结束
- 无法使用外部工具(文件、网络、计算等)
- 无法分步骤解决复杂问题
- 无法根据执行结果调整策略
Agent 解决的问题:
- 工具调用问题:让 AI 能够操作现实世界工具
- 比如:读取文件、执行计算、查询数据库
- 传统 AI 只能"说",Agent 能"做"
- 复杂任务分解问题:将大任务拆解为可执行的小步骤
- 比如:"分析公司数据并生成报告"需要多个阶段
- Agent 能像项目经理一样分步执行
- 动态调整问题:根据执行结果实时调整策略
- 传统 AI:错了就错了,无法修正
- Agent:能根据反馈重新思考、重新尝试
Agent 设计模式解决的问题:
Agent 实现了 AI 从“能说”到“能做”的关键问题,但是实现不只是简单地调用模型、提供工具,而是一项系统工程。要想真正发挥 AI 的潜力,离不开良好的架构设计。
这正是 Agent 设计模式的价值,它将 Agent 的实现方式标准化,提升了系统的可用性和准确率。无论是调用工具、分步骤处理复杂任务,还是根据执行结果动态调整策略,这些模式都提供了经过实践验证的架构。它们把常见的设计问题转化为可复用的解决方案,让开发者不必再从零开始摸索如何组织 AI 的思考、行动与规划。
借助这些模式,开发者可以更专注于构建真正实用、可靠的智能系统,让 AI 不仅“能想会说”,更能“动手执行”。
ReAct 设计模式:边思考边行动
核心思想

传统大语言模型通常只有推理(Reason Only)或者只有执行(Act Only), 而 ReAct(Reasoning + Acting)的核心是 "在行动中思考"。它模拟了人类解决问题的方式:
- 先思考当前情况和目标
- 然后行动(调用工具)
- 观察行动结果
- 根据结果再次思考下一步
- 循环直到问题解决

实现原理分析
关键代码结构:
// 简化版实现逻辑
for (let i = 0; i < maxLoops; i++) {
// 1. 思考:LLM分析当前情况,决定做什么
const { thought, action, args, final } = await llmThink();
if (final) {
// 任务完成
break;
}
// 2. 行动:调用具体的工具
const result = await callTool(action, args);
// 3. 观察:将结果作为下一次思考的输入
context.push(`观察到:${result}`);
}
为什么需要严格的JSON格式?
// 系统提示词要求:
const SYSTEM = `你必须用这个格式响应:
{
"thought": "你的思考过程",
"action": "工具名(可选)",
"args": {参数},
"final": "最终结果(可选)"
}`;
原因:
- 程序可解析性:非结构化文本难以被程序理解
- 确定性:确保每次输出结构一致
- 错误处理:格式错误时可以明确识别和修复
工具调用机制:
// 工具注册系统
const tools = {
"read_file": {
description: "读取文件内容",
execute: (args) => fs.readFile(args.path)
},
"search_web": {
description: "搜索网页",
execute: (args) => fetch(searchAPI + args.query)
}
};
// 统一调用接口
async function callTool(name, args) {
const tool = tools[name];
if (!tool) return { error: "工具不存在" };
try {
const result = await tool.execute(args);
return { success: true, data: result };
} catch (e) {
return { success: false, error: e.message };
}
}
执行流程示例:
任务:"读取 report.txt 文件,统计其中'错误'出现的次数"
循环1:
思考:需要先读取文件内容
行动:调用read_file,参数{path: "report.txt"}
观察:文件内容为"系统运行正常,无错误发生"
循环2:
思考:需要统计"错误"一词的出现次数
行动:调用count_string,参数{text: "系统运行正常,无错误发生", target: "错误"}
观察:出现次数为0
循环3:
思考:任务完成,统计结果为0次
最终:在report.txt文件中,"错误"一词出现了0次
ReAct 解决的问题
- 工具选择的智能性:LLM 根据当前情况选择最合适的工具
- 参数生成的准确性:LLM 根据工具描述生成正确的参数
- 结果驱动的迭代:基于观察结果决定下一步行动
- 错误恢复能力:工具调用失败时可以尝试其他方法
适用场景
- 工具密集型任务:需要调用多个工具
- 探索性任务:路径不明确,需要试错
- 实时交互任务:需要根据反馈调整
Plan-and-Execute 设计模式:先规划再执行
核心思想

Plan-and-Execute 的核心是 "先谋定而后动"。它模拟了专业项目管理:
- 规划阶段:先制定完整的执行计划
- 执行阶段:按计划逐步执行
- 监控阶段:监控执行结果
- 重规划阶段:失败时调整计划

实现原理分析
三层架构设计:
// 1. 规划层 - 生成蓝图
async function generatePlan(task) {
// 提示词强调"做什么",而不是"怎么做"
const prompt = `你是一位项目经理,请将任务分解为3-6个可执行的步骤。
任务:${task}
要求:
- 每个步骤描述要达到的目标
- 不要描述具体实现细节
- 步骤间有逻辑顺序
输出格式:{ "steps": [{"step": "描述"}] }`;
return await llmGenerate(prompt);
}
// 2. 执行层 - 执行每个步骤(可用ReAct)
async function executeStep(step) {
// 对每个步骤使用ReAct执行
return await runReAct({ task: step.step });
}
// 3. 监控层 - 处理失败和重规划
async function monitorExecution(plan, results) {
for (let i = 0; i < plan.steps.length; i++) {
const result = results[i];
if (result.failed) {
// 触发重规划
const newPlan = await replan({
originalTask,
failedStep: plan.steps[i],
failureReason: result.error,
completedSteps: results.slice(0, i)
});
// 用新计划重新开始
return await executePlan(newPlan);
}
}
}
重规划机制详解:
async function replan(context) {
const prompt = `原任务:${context.originalTask}
执行情况:
- 已完成:${context.completedSteps.length}个步骤
- 失败步骤:${context.failedStep.step}
- 失败原因:${context.failureReason}
请生成新的计划,避免同样的失败。`;
// LLM会分析失败原因,调整后续步骤
const newPlan = await llmGenerate(prompt);
return {
...newPlan,
// 保留已成功的步骤
completedSteps: context.completedSteps
};
}
为什么需要"高层规划"?
- 视野问题:LLM 单次思考只能看到局部,规划让 AI 看到全局
- 顺序问题:复杂任务有依赖关系(先 A 后 B)
- 资源问题:提前考虑可能需要哪些工具和数据
- 容错问题:提前识别可能的失败点
执行流程示例:
任务:"分析系统日志,找出错误,生成报告"
阶段1:规划
{
"steps": [
{"step": "收集所有日志文件"},
{"step": "分析日志中的错误模式"},
{"step": "统计错误频率和时间分布"},
{"step": "生成分析报告"}
]
}
阶段2:执行
步骤1:收集日志 → 成功
步骤2:分析错误 → 失败(日志格式不一致)
阶段3:重规划
新计划:
{
"steps": [
{"step": "收集所有日志文件"},
{"step": "统一日志格式"},
{"step": "分析错误模式"},
{"step": "统计错误信息"},
{"step": "生成分析报告"}
]
}
阶段4:继续执行...
Plan-and-Execute 解决的问题
- 复杂任务分解:将大问题拆解为可管理的小问题
- 执行顺序优化:合理安排步骤顺序,避免无效尝试
- 失败处理系统化:不是简单重试,而是调整策略
- 进度可追踪:明确知道完成了多少,还剩多少
与 ReAct 的关键区别
| 方面 | ReAct | Plan-and-Execute |
|---|---|---|
| 思考粒度 | 细粒度(每一步) | 粗粒度(每个阶段) |
| 规划时间 | 实时规划 | 预先规划 |
| 错误处理 | 立即调整 | 重新规划 |
| 适用规模 | 中小任务 | 中大任务 |
| 资源消耗 | 较低 | 较高(多次调用) |
适用场景
- 多阶段项目:有明显阶段划分的任务
- 可能失败的任务:需要备用方案的任务
- 资源受限任务:需要合理安排资源
- 长期任务:需要保存进度和状态
选择指南
选择 ReAct :
- 任务相对简单直接
- 需要快速响应和迭代
- 工具调用路径清晰
- 不需要长期规划
选择 Plan-and-Execute :
- 任务复杂,有多个阶段
- 步骤间有依赖关系
- 可能遇到多种失败情况
- 需要可追踪的执行进度
本质区别:思考的时空维度
- ReAct:横向思考 - 在当前状态下,下一步做什么?
- Plan-and-Execute:纵向思考 - 整个任务如何分阶段完成?
总结:为什么需要 Agent 设计模式
解决的本质问题
- 连接 AI 与现实世界
- 传统 AI:停留在语言层面
- Agent:能实际操作工具,影响现实
- 处理复杂度超越人类单次思考的任务
- 传统 AI:受限于单次对话长度和结构
- Agent:能分步骤、分阶段解决复杂问题
- 实现自我修正和适应
- 传统 AI:输出即结束
- Agent:能根据反馈调整策略
参考资料
- ReAct: Synergizing Reasoning and Acting in Language Models
- Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models
- Plan-and-Execute Agents
- Reflection Agents
![[agent-desgin-pattern-demo-main.zip]]